
#include "graphics/boundingvolume.h"

namespace dw
{
namespace graphics
{

// BoundingBox

																	BoundingBox::BoundingBox()
{
}

																	BoundingBox::BoundingBox(const Point3f& center, const float width, const float height, const float depth) : 
	Cuboid(center, width, height, depth)
{
}

																	BoundingBox::BoundingBox(const Point3f& center, const Vector3f& size) : 
	Cuboid(center, size)
{
}

																	BoundingBox::BoundingBox(const Point3f& min, const Point3f& max) : 
	Cuboid(min, max)
{
}

																	BoundingBox::~BoundingBox()
{
}

// AxisAlignedBoundingBox

																	AxisAlignedBoundingBox::AxisAlignedBoundingBox()
{
}

																	AxisAlignedBoundingBox::AxisAlignedBoundingBox(const Point3f& center, const float width, const float height, const float depth) : 
	BoundingBox(center, width, height, depth)
{
}

																	AxisAlignedBoundingBox::AxisAlignedBoundingBox(const Point3f& center, const Vector3f& size) : 
	BoundingBox(center, size)
{
}

																	AxisAlignedBoundingBox::AxisAlignedBoundingBox(const Point3f& min, const Point3f& max) : 
	BoundingBox(min, max)
{
}

																	AxisAlignedBoundingBox::~AxisAlignedBoundingBox()
{
}

void AxisAlignedBoundingBox::getVertices(std::vector< Point3f >& points) const
{
	points.clear();
	Point3f min = this->center - this->size / 2.0f;
	Point3f max = this->center + this->size / 2.0f;

	points.push_back(Point3f(min.x, min.y, min.z));
	points.push_back(Point3f(max.x, min.y, min.z));
	points.push_back(Point3f(max.x, min.y, max.z));
	points.push_back(Point3f(min.x, min.y, max.z));
	points.push_back(Point3f(min.x, max.y, min.z));
	points.push_back(Point3f(max.x, max.y, min.z));
	points.push_back(Point3f(max.x, max.y, max.z));
	points.push_back(Point3f(min.x, max.y, max.z));
}

bool AxisAlignedBoundingBox::intersects(const Point3f& p) const 
{
	Point3f min = center - size;
	Point3f max = center - size;

	return ((p.x > min.x) && (p.x < max.x) 
		&& (p.y > min.x) && (p.y < max.y) 
		&& (p.z > min.z) && (p.z < max.z));
}

bool AxisAlignedBoundingBox::intersects(const AxisAlignedBoundingBox& aabb) const
{
	maths::Vector3f dist = aabb.center - this->center;
	maths::Vector3f exts = (aabb.size + this->size) / 2.f;

	return std::abs(dist.x) <= exts.x
		&& std::abs(dist.y) <= exts.y
		&& std::abs(dist.z) <= exts.z;
}

void AxisAlignedBoundingBox::transform(const Matrix4f& m)
{
	center = Point3f::transform(center, m);
}

void AxisAlignedBoundingBox::merge(const AABBox& aabb)
{

}


// OrientedBoundingBox


																	OrientedBoundingBox::OrientedBoundingBox()
{
}

																	OrientedBoundingBox::~OrientedBoundingBox()
{
}

void OrientedBoundingBox::getVertices(std::vector< Point3f >& points) const
{
	points.clear();	
}


bool OrientedBoundingBox::intersects(const Point3f& p) const
{
	// DW_NOT_IMPLEMENTED;
	return false;
}

void OrientedBoundingBox::transform(const Matrix4f& m)
{
	// DW_NOT_IMPLEMENTED;
}



// BoundingSphere


																	BoundingSphere::BoundingSphere()
{
}

																	BoundingSphere::~BoundingSphere()
{
}

bool BoundingSphere::intersects(const Vector3f& p) const 
{
	if ((p - position).length() <= radius) return true;
	else return false;
}

void BoundingSphere::transform(const Matrix4f& m)
{
	dwFail("Not implemented");
}

} // namespace graphics
} // namespace dw
